
;=================================================
;	Fat12.inc
;=================================================

%ifndef __FAT12_INC_67343546FDCC56AAB872_INCLUDED__
%define __FAT12_INC_67343546FDCC56AAB872_INCLUDED__

bits	16

%include "Floppy16.inc"


;======================================
;Our constants
;======================================
%define ROOT_OFFSET 0x2e00
%define FAT_SEG 0x2c0
%define ROOT_SEG 0x2e0


;======================================
;LoadRoot() - Load Root Directory Table 
;======================================

LoadRoot:
	
		pusha
		push	es		;store registers
		
		xor		cx, cx
		xor		dx, dx
		mov		ax, 32	;32byte directory
		
		mul		WORD [bpbRootEntries]
		div		WORD [bpbBytesPerSector]
		
		xchg	ax, cx	;move into ax
		
		mov		al, byte [bpbNumberOfFATs]
		mul		word [bpbSectorsPerFAT]
		add		ax, word [bpbReservedSectors]
		mov		word [datasector], ax	;base of root directory
		add		word [datasector], cx
		
		push	word ROOT_SEG
		pop		es
		mov		bx, 0
		call	ReadSectors
		
		pop		es
		popa			;restore registers
		ret
		
;======================================
;LoadFAT() - Load FAT Table 
;======================================

LoadFAT:

		pusha
		push	es		;store registers
		
		xor		ax, ax
		mov	al, BYTE [bpbNumberOfFATs]
		mul		word [bpbSectorsPerFAT]
		
		mov		cx, ax
		mov		ax, word [bpbReservedSectors]
		
		push word FAT_SEG
		pop		es
		xor		bx, bx
		call	ReadSectors
		pop		es
		popa		;restore registers
		ret			;return
		
;======================================
;FindFile() - Search for filename in root table 
;======================================

FindFile:

		push	cx			;store registers
		push	dx
		push	bx
		mov		bx, si		;copy filename to bx for later use

		mov		cx,	word[bpbRootEntries]
		mov		di,	ROOT_OFFSET
		cld					;important to clear direction flag
		
.LOOP:
		push	cx
		mov		cx, 11		
		mov		si, bx
		push	di
		rep		cmpsb		;test for filename match
		
		pop		di
		je		.Found
		pop		cx
		add		di, 32		;queue next directory entry
		loop    .LOOP		

.NotFound:
		pop		bx			;restore registers
		pop		dx
		pop		cx
		
		mov		ax, -1		;set error code
		ret					;return
		
.Found:
		pop		ax			;ax now contains entry of file
		pop		bx			;restore registers
		pop		dx
		pop		cx
		ret
		
;======================================
;LoadFile() - Load file 
;======================================

LoadFile:

		xor		ecx, ecx
		push	ecx
		
.FIND_FILE:
		push	bx
		push	bp
		call	FindFile
		
		cmp		ax, -1
		jne		.LOAD_IMAGE_PRE
		pop		bp
		pop		bx
		pop		ecx
		mov		ax, -1
		ret
		
.LOAD_IMAGE_PRE:
		sub		edi, ROOT_OFFSET
		sub		eax, ROOT_OFFSET
		push	word ROOT_SEG
		pop		es
		mov		dx, word [es:di + 0x001A]
		mov		word [cluster], dx
		pop		bx
		pop		es
		push	bx
		push	es
		call	LoadFAT		;Load the FAT to 0x7c00
		
.LOAD_IMAGE:
		mov     ax, WORD [cluster]		;cluster to read
		pop		es
		pop     bx
		call    ClusterLBA				;convert cluster to LBA
 		xor     cx, cx
		mov     cl, BYTE [bpbSectorsPerCluster]	;sectors to read
		call    ReadSectors	

		pop	ecx				;increment sector count
		inc	ecx
		push	ecx

		push    bx			;save registers for next iteration
		push    es

		mov	ax, FAT_SEG
		mov	es, ax
		xor	bx, bx


		mov     ax, WORD [cluster]	;identify current cluster
		mov     cx, ax				;copy current cluster
		mov     dx, ax				;copy current cluster
		shr     dx, 0x0001			;Divide by two
		add     cx, dx				;sum for (3/2)

		mov     bx, 0				;location of FAT in memory
		add     bx, cx				;index into FAT
		mov     dx, WORD [es:bx]	;read two bytes from FAT
		test    ax, 0x0001
		jnz     .ODD_CLUSTER

.EVEN_CLUSTER:
		and     dx, 0000111111111111b	;take low twelve bits
		jmp     .DONE

.ODD_CLUSTER:
		shr     dx, 0x0004		;take high twelve bits
	          
.DONE:
		mov     WORD [cluster], dx	;store new cluster
		cmp     dx, 0x0FF0			;test for end of file marker (0xFF)
		jb      .LOAD_IMAGE			;No? Go on to next cluster then

DONE:
		pop	es				;restore all registers
		pop	bx
		pop     ecx
		xor     ax, ax		;return success code
		ret


%endif 
